package cn.zzuisa.bluebox.base.exception;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import cn.zzuisa.bluebox.base.facade.R;
import org.apache.shiro.authz.AuthorizationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

import com.alibaba.druid.pool.DataSourceClosedException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException;

/**
 * 异常处理器
 *
 * @author Ao
 * @since 1.0.0 2016-10-27
 */
@RestControllerAdvice
public class RRExceptionHandler {
	private Logger logger = LoggerFactory.getLogger(getClass());

	/**
	 * 处理自定义异常
	 */
	@ExceptionHandler(RRException.class)
	public R<String> handleRRException(RRException e) {
		R<String> r = new R<String>(e.getCode(), e.getMessage());
		return r;
	}

	@ExceptionHandler(DuplicateKeyException.class)
	public R<String> handleDuplicateKeyException(DuplicateKeyException e) {
		logger.error(e.getMessage(), e);
		return R.error("数据库中已存在该记录");
	}

	@ExceptionHandler(AuthorizationException.class)
	public R<String> handleAuthorizationException(AuthorizationException e) {
		logger.error(e.getMessage(), e);
		return R.error("没有权限，请联系管理员授权");
	}

	@ExceptionHandler(HttpMessageNotReadableException.class)
	public R<String> handleException(HttpMessageNotReadableException e) {
		logger.error(e.getMessage(), e);
		return R.error("请求体格式不对，请检查");
	}

	@ExceptionHandler(JsonMappingException.class)
	public R<String> handleException(JsonMappingException e) {
		logger.error(e.getMessage(), e);
		return R.error("json解析异常，请检查数据格式");
	}
	@ExceptionHandler(BindException.class)
	public R<String> handleException(BindException e) {
		logger.error(e.getMessage(), e.getCause().getMessage());
		return R.error("参数的数据类型异常，");
	}
	@ExceptionHandler(MethodArgumentTypeMismatchException.class)
	public R<String> handleException(MethodArgumentTypeMismatchException e) {
		logger.error(e.getMessage(), e.getCause().getMessage());
		return R.error("参数的数据类型异常，" + e.getName() + "不能为" + e.getValue());
	}
	@ExceptionHandler(NumberFormatException.class)
	public R<String> handleException(NumberFormatException e) {
		logger.error(e.getMessage(), e);
		return R.error("数据类型异常");
	}
	@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
	public R<String> handleException(HttpRequestMethodNotSupportedException e) {
		logger.error(e.getMessage(), e);
		return R.error("http动词不合法：" + e.getMessage());
	}

	@ExceptionHandler(DataSourceClosedException.class)
	public R<String> handleException(DataSourceClosedException e) {
		logger.error(e.getMessage(), e);
		return R.error("数据源异常，请联系管理员");
	}

	@ExceptionHandler(Exception.class)
	public R<String> handleException(Exception e) {
		logger.error(e.getMessage(), e);
		return R.error("异常");
	}

	/**
	 * 可能主键插入重复或者其他SQL错误
	 * @param e
	 * @param request
	 * @return
	 */
	@ExceptionHandler(MySQLIntegrityConstraintViolationException.class)
	public R<String> handleMySQLIntegrityConstraintViolationException(MySQLIntegrityConstraintViolationException e , HttpServletRequest request) {
		//String uri = request.getRequestURI();
		Map<String, Object> content = new HashMap<>();
		//content.put("uri", uri);
		String message = e.iterator().next().getMessage();
		content.put("content", message);
		logger.error(e.getMessage(), e);
		return R.error(content.toString());
	}
	/**
	 * 参数校验错误
	 * @param e
	 * @return
	 */
	@ExceptionHandler(MethodArgumentNotValidException.class)
	public R<String> argumentValidException(MethodArgumentNotValidException e) {
		logger.error(e.getMessage(), e);
		return R.error(e.getMessage());
	}
}
